// import { GlobalManager } from './GlobalManager';
import * as path from 'path';
import * as glob from 'glob';
import * as crypto from "crypto";
import * as fs from 'fs';
// import { NCSHOP_PATH, ROOT_PATH, DEFAULT_FACE_IMAGE } from '../config';
import * as multer from 'multer';
import * as uuid from 'uuid';
// import { Member } from '../app/home/ml/member';
import { Container } from 'typedi';
// import { ExpressEX } from './express';
import { time, strtotime } from 'locutus/php/datetime';
// console.log("imported !!!!!");


// export function sendToClient(){
//     var res = GlobalManager.getInstance();
// }

export function log(...args) {
    return console.log.apply(null, arguments);
}

// export function AddControllerDir(dirname: string) {
//     glob(path.join(dirname, '*.js'), function (err, files) {
//         if (err) {
//             log(`扫描${dirname}错误！`);
//             return;
//         }
//         files.forEach(file => {
//             var ctor = require(file).default;
//             Container.bind(file, ctor);
//         });
//     })
// }

// export function md5(str: any): string {
//     const hash = crypto.createHash('md5');
//     var decrypted = hash.update(str);
//     return decrypted.digest('hex');
// }






var Redis = require('ioredis');
var redis = new Redis();
export function SetCache(name, val, expr?) {
    if (!expr) expr = 24 * 3600
    redis.set(name, val, 'EX', expr);
}
export function GetCache(name): Promise<any> {
    return redis.get(name);
}
// export function RegisterController(){

// }

var _date = require('locutus/php/datetime/date');

export function date(...args) {
    return _date.apply(null, args);
}

export function GetTimeStamp(): string {
    var date: any = new Date();
    var timestamp = Math.trunc(Date.parse(date) / 1000);
    return timestamp.toString();
}

async function TheadFuns(...args: Function[]);
async function TheadFuns(...args: object[]);
async function TheadFuns(...args: any[]) {
    if (typeof args[0] == 'function') {
        var ps = (<any[]>args).map(callback => {
            return new Promise(async (resolve, reject) => {
                try {
                    const ret = await callback();
                    resolve(await ret);
                }
                catch (e) {
                    console.log(e);
                    reject(null);
                }
            });
        });
        return await Promise.all(ps);
    }
    else if (args[0] instanceof Object) {
        var keys = Object.keys(args[0]);
        var promise = Object.values(args[0]).map(cb => {
            return new Promise(async (resolve, reject) => {
                try {
                    const ret = await cb();
                    resolve(await ret);
                }
                catch (e) {
                    console.log(e);
                    reject(e);
                }
            });
        });
        var rets = await Promise.all(promise);
        var result = {};
        rets.forEach((ret, index) => {
            (<any>result)[keys[index]] = ret;
        });
        return result;
    }
}

export { TheadFuns };

export function failed(msg?) {
    return {
        success: false,
        msg: msg
    }
}
export function success(msg?) {
    return {
        success: true,
        msg : msg
    }
}

export function UUID() {
    return uuid.v1();
}


const Serialize = require('php-serialize')
export function PHPSerialize(item) {
    return Serialize.serialize(item);
}
export function PHPUnserialize(item) {
    return Serialize.unserialize(item);
}


// export async function GetFace(user: Member) {
//     const filepath = path.join(NCSHOP_PATH, 'data', 'upload', 'shop', 'avatar_' + user.member_id + '.jpg');
//     var p = new Promise(function (resolve, reject) {
//         fs.exists(filepath, function (bool) {
//             resolve(bool)
//         });
//     });
//     return (await p) ? '/data/upload/shop/avatar_' + user.member_id + '.jpg' : DEFAULT_FACE_IMAGE;
// }

var captchapng = require('captchapng');
export function GetCaptcha() {
    var num = 0;
    var p = new captchapng(80, 30, num = Math.floor(Math.random() * 9000 + 1000)); // width,height,numeric captcha
    p.color(0, 0, 0, 0);  // First color: background (red, green, blue, alpha)
    p.color(0, 102, 255, 255); // Second color: paint (red, green, blue, alpha)

    var img = p.getBase64();
    var imgbase64 = new Buffer(img, 'base64');
    return [num, imgbase64];
}

export function Ksort(inputArr, sort_flags?) {
    //  discuss at: http://phpjs.org/functions/ksort/  
    // original by: GeekFG (http://geekfg.blogspot.com)  
    // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)  
    // improved by: Brett Zamir (http://brett-zamir.me)  
    //        note: The examples are correct, this is a new way  
    //        note: This function deviates from PHP in returning a copy of the array instead  
    //        note: of acting by reference and returning true; this was necessary because  
    //        note: IE does not allow deleting and re-adding of properties without caching  
    //        note: of property position; you can set the ini of "phpjs.strictForIn" to true to  
    //        note: get the PHP behavior, but use this only if you are in an environment  
    //        note: such as Firefox extensions where for-in iteration order is fixed and true  
    //        note: property deletion is supported. Note that we intend to implement the PHP  
    //        note: behavior by default if IE ever does allow it; only gives shallow copy since  
    //        note: is by reference in PHP anyways  
    //        note: Since JS objects' keys are always strings, and (the  
    //        note: default) SORT_REGULAR flag distinguishes by key type,  
    //        note: if the content is a numeric string, we treat the  
    //        note: "original type" as numeric.  
    //  depends on: i18n_loc_get_default  
    //  depends on: strnatcmp  
    //   example 1: data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};  
    //   example 1: data = ksort(data);  
    //   example 1: $result = data  
    //   returns 1: {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'}  
    //   example 2: ini_set('phpjs.strictForIn', true);  
    //   example 2: data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'};  
    //   example 2: ksort(data);  
    //   example 2: $result = data  
    //   returns 2: {1: 'Kevin', 2: 'van', 3: 'Zonneveld'}  

    var tmp_arr = {},
        keys = [],
        sorter, i, k, that = this,
        strictForIn = false,
        populateArr = {};

    switch (sort_flags) {
        case 'SORT_STRING':
            // compare items as strings  
            sorter = function (a, b) {
                return that.strnatcmp(a, b);
            };
            break;
        case 'SORT_LOCALE_STRING':
            // compare items as strings, original by the current locale (set with  i18n_loc_set_default() as of PHP6)  
            var loc = this.i18n_loc_get_default();
            sorter = this.php_js.i18nLocales[loc].sorting;
            break;
        case 'SORT_NUMERIC':
            // compare items numerically  
            sorter = function (a, b) {
                return ((a + 0) - (b + 0));
            };
            break;
        // case 'SORT_REGULAR': // compare items normally (don't change types)  
        default:
            sorter = function (a, b) {
                var aFloat = parseFloat(a),
                    bFloat = parseFloat(b),
                    aNumeric = aFloat + '' === a,
                    bNumeric = bFloat + '' === b;
                if (aNumeric && bNumeric) {
                    return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
                } else if (aNumeric && !bNumeric) {
                    return 1;
                } else if (!aNumeric && bNumeric) {
                    return -1;
                }
                return a > b ? 1 : a < b ? -1 : 0;
            };
            break;
    }

    // Make a list of key names  
    for (k in inputArr) {
        if (inputArr.hasOwnProperty(k)) {
            keys.push(k);
        }
    }
    keys.sort(sorter);

    // BEGIN REDUNDANT  
    this.php_js = this.php_js || {};
    this.php_js.ini = this.php_js.ini || {};
    // END REDUNDANT  
    strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js
        .ini['phpjs.strictForIn'].local_value !== 'off';
    populateArr = strictForIn ? inputArr : populateArr;

    // Rebuild array with sorted key names  
    for (i = 0; i < keys.length; i++) {
        k = keys[i];
        tmp_arr[k] = inputArr[k];
        if (strictForIn) {
            delete inputArr[k];
        }
    }
    for (i in tmp_arr) {
        if (tmp_arr.hasOwnProperty(i)) {
            populateArr[i] = tmp_arr[i];
        }
    }

    return strictForIn || populateArr;
}

export function Urlencode(str) {
    //       discuss at: http://locutus.io/php/urlencode/
    //      original by: Philip Peterson
    //      improved by: Kevin van Zonneveld (http://kvz.io)
    //      improved by: Kevin van Zonneveld (http://kvz.io)
    //      improved by: Brett Zamir (http://brett-zamir.me)
    //      improved by: Lars Fischer
    //         input by: AJ
    //         input by: travc
    //         input by: Brett Zamir (http://brett-zamir.me)
    //         input by: Ratheous
    //      bugfixed by: Kevin van Zonneveld (http://kvz.io)
    //      bugfixed by: Kevin van Zonneveld (http://kvz.io)
    //      bugfixed by: Joris
    // reimplemented by: Brett Zamir (http://brett-zamir.me)
    // reimplemented by: Brett Zamir (http://brett-zamir.me)
    //           note 1: This reflects PHP 5.3/6.0+ behavior
    //           note 1: Please be aware that this function
    //           note 1: expects to encode into UTF-8 encoded strings, as found on
    //           note 1: pages served as UTF-8
    //        example 1: urlencode('Kevin van Zonneveld!')
    //        returns 1: 'Kevin+van+Zonneveld%21'
    //        example 2: urlencode('http://kvz.io/')
    //        returns 2: 'http%3A%2F%2Fkvz.io%2F'
    //        example 3: urlencode('http://www.google.nl/search?q=Locutus&ie=utf-8')
    //        returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3DLocutus%26ie%3Dutf-8'
    str = (str + '')
    // Tilde should be allowed unescaped in future versions of PHP (as reflected below),
    // but if you want to reflect current
    // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
    return encodeURIComponent(str)
        .replace(/!/g, '%21')
        .replace(/'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A')
        .replace(/%20/g, '+')
}

// export async function GetPaymentInfo(pay_sn, payment_code) {
//     var data = await TheadFuns({
//         payinfo: async () => {
//             return GetRepository(Payment).findOne({
//                 where: {
//                     payment_code: payment_code
//                 }
//             });
//         },
//         order: async () => {
//             return await GetRepository(Order).findOne({
//                 where: {
//                     pay_sn: pay_sn
//                 }
//             })
//         }
//     });
//     return [data.payinfo,data.order];
// }

export function getTerm($date = null) {
    if (!$date) {
        $date = time();
    }
    //十点后，22点之前，每10分钟一期
    let $hour0 = strtotime(date("Y-m-d"));
    let $hour2 = $hour0 + 2 * 3600;
    let $hour10 = $hour0 + 10 * 3600;
    let $hour22 = $hour0 + 22 * 3600;
    if ($date < $hour2) {
        return Math.ceil(($date - $hour0) / 300);
    }
    else if ($date >= $hour10 && $date <= $hour22) {
        return Math.floor(($date - $hour10) / 600) + 25;
    }
    else if ($date >= $hour22) {
        return Math.floor(($date - $hour22) / 300) + 97;
    }
    return -1;
}

export function returnFloat(value) {
    value = Math.floor(parseFloat(value) * 100) / 100;
    var xsd = value.toString().split(".");
    if (xsd.length == 1) {
        value = value.toString() + ".00";
        return value;
    }
    if (xsd.length > 1) {
        if (xsd[1].length < 2) {
            value = value.toString() + "0";
        }
        return value;
    }
}
